#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <bitset>

using namespace std;

const int BATCH_BITS = 8; // 每次处理8个位（1字节）
const int FILE_COUNT = 128;
const int BITS_PER_BYTE = 8;

struct FileHandler {
    ifstream stream;
    vector<char> buffer;
    size_t byte_pos = 0;
    int bit_pos = BITS_PER_BYTE - 1; // 从高位开始

    explicit FileHandler(const string& filename) : stream(filename, ios::binary) {
        if (stream) {
            stream.seekg(0, ios::end);
            size_t size = stream.tellg();
            stream.seekg(0, ios::beg);
            buffer.resize(size);
            stream.read(buffer.data(), size);
        }
    }

    bool get_next_bit() {
        if (byte_pos >= buffer.size()) return false;
        bool bit = (buffer[byte_pos] >> bit_pos) & 1;
        if (--bit_pos < 0) {
            bit_pos = BITS_PER_BYTE - 1;
            ++byte_pos;
        }
        return bit;
    }
};

int main(int argc,char* argv[]) {

    if(argc!=3)
    {
        std::cerr<<"exe <input_dir> <output_file>\n";
        return 1;

    }
    vector<FileHandler> handlers;
    handlers.reserve(FILE_COUNT);
    std::string input_dir=argv[1];
    // 初始化所有文件处理器
    for (int i = 1; i <= FILE_COUNT; ++i) {
        handlers.emplace_back(input_dir + "/" + std::to_string(i) + ".bin");
    }

    ofstream output(argv[2], ios::binary);
    vector<bitset<FILE_COUNT>> bit_groups;

    bool has_more_data = true;
    while (has_more_data) {
        has_more_data = false;
        bit_groups.clear();
        bit_groups.resize(BATCH_BITS); // 准备处理8个位层

        // 并行收集8个位层的数据
        for (int file_idx = 0; file_idx < FILE_COUNT; ++file_idx) {
            for (int bit_layer = 0; bit_layer < BATCH_BITS; ++bit_layer) {
                bool bit = handlers[file_idx].get_next_bit();
                if (bit) has_more_data = true;
                bit_groups[bit_layer].set(file_idx, bit);
            }
        }

        // 将8个位层打包写入文件
        for (auto& bits : bit_groups) {
            vector<unsigned char> packed_bytes(16, 0);
            for (int byte_idx = 0; byte_idx < 16; ++byte_idx) {
                for (int bit_idx = 0; bit_idx < 8; ++bit_idx) {
                    if (bits[byte_idx*8 + bit_idx]) {
                        packed_bytes[byte_idx] |= (1 << (7 - bit_idx));
                    }
                }
            }
            output.write(reinterpret_cast<char*>(packed_bytes.data()), packed_bytes.size());
        }
    }

    return 0;
}